package com.threegold.listview.common;

import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

public class CircleLoadingView extends Component implements Component.DrawTask, Component.EstimateSizeListener, Component.BindStateChangedListener {

    /**
     * 绘制进度的画笔
     */
    private Paint progressPaint;
    /**
     * loading加载状态的变化率
     */
    private float changeRate = 0;
    /**
     * 中心点x坐标
     */
    private float centerX;
    /**
     * 中心点y坐标
     */
    private float centerY;
    /**
     * 宽高的较小值
     */
    private int minSize;
    /**
     * 绘制loading时候的进度框矩形
     */
    private final RectFloat progressRect = new RectFloat();
    /**
     * 执行loading的属性动画对象
     */
    private AnimatorValue loadingAnimator;
    /**
     * 进度颜色
     */
    private Color progressColor;
    /**
     * 进度背景颜色
     */
    private Color bgColor;
    /**
     * 绘制弧形的arc参数对象
     */
    private final Arc arc = new Arc();

    public CircleLoadingView(Context context) {
        this(context, null);
    }

    public CircleLoadingView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public CircleLoadingView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        addDrawTask(this);
        setEstimateSizeListener(this);
        setBindStateChangedListener(this);
        progressColor = new Color(0xFFFF0000);
        bgColor = new Color(0xFFDDDDDD);
        initPaint();
    }

    private void initPaint() {
        progressPaint = new Paint();
        progressPaint.setAntiAlias(true);
        progressPaint.setStyle(Paint.Style.STROKE_STYLE);
        progressPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
    }

    public void setBgColor(Color bgColor) {
        this.bgColor = bgColor;
    }

    public void setProgressColor(Color progressColor) {
        this.progressColor = progressColor;
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        cancelLoadingAnimator();
        if (visibility == VISIBLE) {
            startLoadingAnimator();
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        // 绘制背景
        arc.setArc(0, 360, false);
        progressPaint.setColor(bgColor);
        canvas.drawArc(progressRect, arc, progressPaint);
        // 绘制旋转进度
        arc.setArc(changeRate * 360, 180, false);
        progressPaint.setColor(progressColor);
        canvas.drawArc(progressRect, arc, progressPaint);
    }

    private void startLoadingAnimator() {
        if (loadingAnimator == null) {
            loadingAnimator = new AnimatorValue();
            loadingAnimator.setDuration(650);
            loadingAnimator.setLoopedCount(AnimatorValue.INFINITE);
            loadingAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                @Override
                public void onUpdate(AnimatorValue animatorValue, float val) {
                    changeRate = val;
                    invalidate();
                }
            });
        }
        loadingAnimator.start();
    }

    private void cancelLoadingAnimator() {
        if (loadingAnimator != null && loadingAnimator.isRunning()) {
            loadingAnimator.cancel();
        }
    }

    @Override
    public boolean onEstimateSize(int widthSpec, int heightSpec) {
        int width = EstimateSpec.getSize(widthSpec);
        int height = EstimateSpec.getSize(heightSpec);
        minSize = Math.min(width, height);
        centerX = width / 2.0f;
        centerY = height / 2.0f;

        float stroke = minSize / 6.0f;
        progressPaint.setStrokeWidth(stroke);
        // 边上留出2px距离
        float progressRadius = minSize / 2.0f - stroke / 2.0f - 2;
        progressRect.left = centerX - progressRadius;
        progressRect.right = centerX + progressRadius;
        progressRect.top = centerY - progressRadius;
        progressRect.bottom = centerY + progressRadius;
        return false;
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        startLoadingAnimator();
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        cancelLoadingAnimator();
    }

}
